package com.xbongbong.paas.script.controller;


import com.google.common.collect.Maps;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.elasticsearch.pojo.XbbAggregatedPage;
import com.xbongbong.paas.elasticsearch.util.EsUtil;
import com.xbongbong.paas.elasticsearch.util.XbbElasticsearchRestTemplate;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.pojo.dto.FixDataJobDTO;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.pro.config.ProBaseConfig;
import com.xbongbong.pro.constant.ElasticConstant;
import com.xbongbong.pro.constant.XbbProConstant;
import com.xbongbong.pro.domain.entity.SpecialUpdateCustomerDataEntity;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.pro.enums.ErrorCodeEnum;
import com.xbongbong.saas.domain.entity.ext.ContractEntityExt;
import com.xbongbong.saas.domain.entity.ext.CustomerEntityExt;
import com.xbongbong.saas.domain.entity.ext.OpportunityEntityExt;
import com.xbongbong.saas.enums.business.ContractEnum;
import com.xbongbong.saas.enums.business.CustomerManagementEnum;
import com.xbongbong.saas.enums.business.SalesOpportunityEnum;
import com.xbongbong.saas.model.ContractModel;
import com.xbongbong.saas.model.CustomerModel;
import com.xbongbong.saas.model.OpportunityModel;
import com.xbongbong.saas.service.CustomerService;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.PageRequest;
import org.springframework.http.MediaType;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;

/**
 * 客戶表单主数据初始化机会创建时间、合同签订时间
 *
 * @author guojun.hu
 * @version v1.0
 * @date 2021/11/18 15:15
 * @since v1.0
 */
@RestController
@RequestMapping(XbbProConstant.API_ROOT_PREFIX + "/script/publicPool/customer")
public class PublicPoolCustomerScriptController {

    private static final Logger LOG = LoggerFactory.getLogger(PublicPoolCustomerScriptController.class);

    @Resource
    private ProBaseConfig proBaseConfig;
    @Resource
    private CustomerService customerService;
    @Resource
    private CustomerModel customerModel;
    @Resource
    private OpportunityModel opportunityModel;
    @Resource
    private ContractModel contractModel;
    @Resource
    private XbbElasticsearchRestTemplate xbbElasticsearchRestTemplate;
    @Resource
    private PaasRedisHelper paasRedisHelper;

    @RequestMapping(value = "/initContractSignTime", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public void initContractSignTime(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws XbbException {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }
        List<String> corpidList = fixDataJobDTO.getCorpidList();
        long currentTime = DateTimeUtil.getInt();
        Map<String, Object> param = new HashMap<>();
        if (CollectionsUtil.isNotEmpty(corpidList)) {
            param.put("corpidIn", corpidList);
        }

        if (Objects.nonNull(fixDataJobDTO.getUpdateTimeStart())) {
            param.put("updateTimeStart", fixDataJobDTO.getUpdateTimeStart());
        }
        param.put("del", 0);
        param.put("flowStatusIn", Arrays.asList(FlowStatusEnum.NOT_NEED_APPROVAL.getType(), FlowStatusEnum.PASS.getType()));

        long totalMaxId = contractModel.getMaxId(param);
        LOG.warn("开始查询合同数据，最大数据ID：{}", totalMaxId);
        Long gteId = 0L;
        //每次查询条数
        Integer pageNum = 5000;
        List<ContractEntityExt> contractEntityExtList = null;
        Long minId = null;
        Long maxId = null;
        int size = 0;
        boolean flag = true;
        while (flag) {
            if (Objects.nonNull(gteId)) {
                param.put("idGte", gteId);
            }
            param.put("start", 0);
            param.put("pageNum", pageNum);
            param.put("orderByStr", "id asc");
            contractEntityExtList = contractModel.findEntitys(param);

            if (CollectionsUtil.isEmpty(contractEntityExtList)) {
                break;
            } else {
                size = contractEntityExtList.size();
                minId = contractEntityExtList.get(0).getId();
                maxId = contractEntityExtList.get(size - 1).getId();
                gteId = maxId;
            }
            if (size < pageNum) {
                flag = false;
            }
            try {
                LOG.warn("开始初始化第{}——{}条数据，本页查询到合同数据{}条", minId, maxId, size);
                //处理机会
                //<客户ID,机会实体> 去重动作
                Map<Long,ContractEntityExt>  contractMap = Maps.newHashMapWithExpectedSize(size);
                //客户ID集合
                List<Long> customerIdList = new ArrayList<>();
                for (ContractEntityExt contractEntityExt : contractEntityExtList) {
                    //考虑到签订时间的大小问题，这里需要做一个比较的动作
                    Long customerId = contractEntityExt.getData().getLong(ContractEnum.LINK_CUSTOMER.getAttr());
                    Long afterSignTime = contractEntityExt.getData().getLong(ContractEnum.SIGN_TIME.getAttr());
                    if (Objects.nonNull(customerId) && Objects.nonNull(afterSignTime)) {
                        if (contractMap.containsKey(customerId)) {
                            ContractEntityExt contract = contractMap.get(customerId);
                            Long beforeSignTime = contract.getData().getLong(ContractEnum.SIGN_TIME.getAttr());
                            if (afterSignTime > beforeSignTime) {
                                contractMap.put(customerId,contractEntityExt);
                            }
                        } else {
                            contractMap.put(customerId,contractEntityExt);
                            customerIdList.add(customerId);
                        }
                    }
                }

                if (customerIdList.size() == 0 ) {
                    continue;
                }

                //通过客户ID集合查询需要更新的客户信息。
                Map<String, Object> customerParam = new HashMap<>();
                customerParam.put("idIn",customerIdList);
                customerParam.put("del", 0);
                List<CustomerEntityExt> customerEntityExtList = customerModel.findEntitys(customerParam);

                List<SpecialUpdateCustomerDataEntity> updateDataEntityList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                for (CustomerEntityExt customerEntityExt : customerEntityExtList) {
                    String corpid = customerEntityExt.getCorpid();
                    Long dataId = customerEntityExt.getDataId();
                    ContractEntityExt contractEntityExt = contractMap.get(dataId);
                    Long newSignTime = contractEntityExt.getData().getLong(ContractEnum.SIGN_TIME.getAttr());
                    //查询客户本身合同最近签订时间比较是否需要进行更新操作
                    Long oldSignTime = customerEntityExt.getData().getLong(CustomerManagementEnum.CONTRACT_SIGN_DATE.getAttr());
                    SpecialUpdateCustomerDataEntity specialUpdateCustomer = new SpecialUpdateCustomerDataEntity();
                    specialUpdateCustomer.setId(dataId);
                    specialUpdateCustomer.setCorpid(corpid);
                    if (Objects.isNull(oldSignTime)) {
                        specialUpdateCustomer.setSysDate1(newSignTime);
                        updateDataEntityList.add(specialUpdateCustomer);
                    } else {
                        if (newSignTime > oldSignTime) {
                            specialUpdateCustomer.setSysDate1(newSignTime);
                            updateDataEntityList.add(specialUpdateCustomer);
                        }
                    }
                }

                if (CollectionsUtil.isNotEmpty(updateDataEntityList)) {
                    customerService.updateBatch4Script(updateDataEntityList);
                }

            } catch (Exception e) {
                LOG.error("id {} 至 {} 处理失败", minId, maxId, e);
            } finally {
                LOG.warn("id {} 至 {} 处理完毕，耗时{}", minId, maxId, DateTimeUtil.getInt() - currentTime);
            }
        }
        LOG.warn("客户合同签订时间数据初始化完成，耗时{}", DateTimeUtil.getInt() - currentTime);
    }



    /**
     * 客户初始化机会创建时间
     */
    @RequestMapping(value = "/initOpportunityAddTime", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public void initOpportunityAddTime(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }
        List<String> corpidList = fixDataJobDTO.getCorpidList();
        long currentTime = DateTimeUtil.getInt();
        Map<String, Object> param = new HashMap<>();
        if (CollectionsUtil.isNotEmpty(corpidList)) {
            param.put("corpidIn", corpidList);
        }

        if (Objects.nonNull(fixDataJobDTO.getAddTimeStart())) {
            param.put("addTimeStart", fixDataJobDTO.getAddTimeStart());
        }
        param.put("del", 0);
        param.put("flowStatusIn", Arrays.asList(FlowStatusEnum.NOT_NEED_APPROVAL.getType(), FlowStatusEnum.PASS.getType()));

        // 查询合同总数
        long totalMaxId = opportunityModel.getMaxId(param);
        LOG.warn("开始查询机会数据，最大数据ID为:{}", totalMaxId);

        Long gteId = 0L;
        //每次查询条数
        Integer pageNum = 5000;
        List<OpportunityEntityExt> opportunityList = null;
        Long minId = null;
        Long maxId = null;
        int size = 0;
        boolean flag = true;
        while (flag) {
            if (Objects.nonNull(gteId)) {
                param.put("idGte", gteId);
            }
            param.put("start", 0);
            param.put("pageNum", pageNum);
            param.put("orderByStr", "id asc");

            opportunityList = opportunityModel.findEntitys(param);
            if (CollectionsUtil.isEmpty(opportunityList)) {
                break;
            } else {
                size = opportunityList.size();
                minId = opportunityList.get(0).getId();
                maxId = opportunityList.get(size - 1).getId();
                gteId = maxId;
            }
            if (size < pageNum) {
                flag = false;
            }
            try {
                LOG.warn("开始初始化第{}——{}条数据，本页查询到机会数据{}条", minId, maxId, size);
                //处理机会
                //<客户ID,机会实体> 去重动作
                Map<Long,OpportunityEntityExt>  opportunityMap = Maps.newHashMapWithExpectedSize(size);
                //客户ID集合
                List<Long> customerIdList = new ArrayList<>();
                for (OpportunityEntityExt opportunityEntityExt : opportunityList) {
                    Long customerId = opportunityEntityExt.getData().getLong(SalesOpportunityEnum.CUSTOMER_NAME.getAttr());
                    if (Objects.nonNull(customerId)) {
                        opportunityMap.put(customerId,opportunityEntityExt);
                        customerIdList.add(customerId);
                    }
                }

                if (customerIdList.size() == 0 ) {
                    continue;
                }

                //通过客户ID集合查询需要更新的客户信息。
                Map<String, Object> customerParam = new HashMap<>();
                customerParam.put("idIn",customerIdList);
                customerParam.put("del", 0);
                List<CustomerEntityExt> customerEntityExtList = customerModel.findEntitys(customerParam);

                List<SpecialUpdateCustomerDataEntity> updateDataEntityList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                for (CustomerEntityExt customerEntityExt : customerEntityExtList) {
                    String corpid = customerEntityExt.getCorpid();
                    Long dataId = customerEntityExt.getDataId();
                    SpecialUpdateCustomerDataEntity specialUpdateCustomer = new SpecialUpdateCustomerDataEntity();
                    specialUpdateCustomer.setId(dataId);
                    specialUpdateCustomer.setCorpid(corpid);
                    OpportunityEntityExt opportunityEntityExt = opportunityMap.get(dataId);
                    specialUpdateCustomer.setSysDate2(opportunityEntityExt.getAddTime());
                    updateDataEntityList.add(specialUpdateCustomer);
                }

                if (CollectionsUtil.isNotEmpty(updateDataEntityList)) {
                    customerService.updateBatch4Script(updateDataEntityList);
                }

            } catch (Exception e) {
                LOG.error("id {} 至 {} 处理失败", minId, maxId, e);
            } finally {
                LOG.warn("id {} 至 {} 处理完毕，耗时{}", minId, maxId, DateTimeUtil.getInt() - currentTime);
            }
        }
        LOG.warn("客户机会创建时间数据初始化完成，耗时{}", DateTimeUtil.getInt() - currentTime);
    }

    /**
     * 用来查灰度环境某条数据es中有么有
     */
    @RequestMapping(value = "/getES2Customer", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String getES2Customer(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery("corpid.keyword",fixDataJobDTO.getCorpid()));
        boolQueryBuilder.filter(termQuery("del", DelEnum.NORMAL.getDel()));
        boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD,IndexTypeEnum.IDX_SAAS_CUSTOMER.getType()));
        boolQueryBuilder.filter(termsQuery("flowStatus", FlowStatusEnum.normalStatus()));
        boolQueryBuilder.filter(termsQuery(FieldTypeEnum.DATAID.getAlias(), fixDataJobDTO.getDataIdList()));
        sourceBuilder.query(boolQueryBuilder);
        sourceBuilder.sort(new FieldSortBuilder("id").order(SortOrder.ASC));
        SearchRequest searchRequest = new SearchRequest(IndexTypeEnum.IDX_SAAS_CUSTOMER.getIndex());
        PageRequest pageRequest = EsUtil.setPage(sourceBuilder, 0, 1000);
        searchRequest.source(sourceBuilder);
        XbbAggregatedPage<PaasFormDataEntityExt> esEntities = xbbElasticsearchRestTemplate.queryForPages(pageRequest, searchRequest, PaasFormDataEntityExt.class);
        List<PaasFormDataEntityExt> content = esEntities.getContent();
        if (CollectionsUtil.isNotEmpty(content)) {
            LOG.info("查询结果{}",content);
            return esEntities.getContent().get(0).getDataId().toString();
        }
        return "未查询到";
    }


    /**
     * 清除测试1的redis
     */
    @RequestMapping(value = "/removeRedisKey", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String removeRedisKey(@RequestBody @Valid  FixDataJobDTO fixDataJobDTO, BindingResult br){
        paasRedisHelper.removeValue(fixDataJobDTO.getXbbCode(), fixDataJobDTO.getCorpid());
        return "查询成功";
    }
}
